# module 'string' -- Un assortiment d'opérations liées aux chaînes de
#                    caractères

# XXX Parmi ces opérations, certaines sont incroyablement lentes et
# devraient être intégrées à l'interpréteur

# Ces quelques chaînes définissent des catégories de caractères, les
# mêmes que le fichier d'en-tête ctype 
whitespace = ' \t\n'
lowercase = 'abcdefghijklmnopqrstuvwxyz'
uppercase = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
letters = lowercase + uppercase
digits = '0123456789'
hexdigits = digits + 'abcdef' + 'ABCDEF'
octdigits = '01234567'

# Ce dictionnaire permet d'assister les fonctions qui convertissent
# majuscules en minuscules (et vice versa)
_caseswap = {}
for i in range(26):
	_caseswap[lowercase[i]] = uppercase[i]
	_caseswap[uppercase[i]] = lowercase[i]
del i

# convertit les lettres MAJUSCULES en minuscules
def lower(s):
	res = ''
	for c in s:
		if 'A' <= c <= 'Z': c = _caseswap[c]
		res = res + c
	return res

# Convertit les lettres minuscules en MAJUSCULES
def upper(s):
	res = ''
	for c in s:
		if 'a' <= c <= 'z': c = _caseswap[c]
		res = res + c
	return res

# Convertit les lettres minuscules en MAJUSCULES, et les lettres
# MAJUSCULES en minuscules
def swapcase(s):
	res = ''
	for c in s:
		if 'a' <= c <= 'z' or 'A' <= c <= 'Z': c = _caseswap[c]
		res = res + c
	return res

# Retire les tabulations et espaces se trouvant au début et à la fin d'une
# chaîne
def strip(s):
	i, j = 0, len(s)
	while i < j and s[i] in whitespace: i = i+1
	while i < j and s[j-1] in whitespace: j = j-1
	return s[i:j]

# Transforme une chaîne en une liste de mots; les mots de la chaîne sont
# délimités par des espaces ou des tabulations 
# NB : split(s) NE FAIT PAS la même chose que splitfields(s, ' ')!
def split(s):
	res = []
	i, n = 0, len(s)
	while i < n:
		while i < n and s[i] in whitespace: i = i+1
		if i = n: break
		j = i
		while j < n and s[j] not in whitespace: j = j+1
		res.append(s[i:j])
		i = j
	return res

# Transforme une chaîne en une liste de champs; les champs de la chaîne sont
# délimités par la chaîne spécifiée
# NB : splitfields(s, ' ') NE FAIT PAS la même chose que split(s)!
def splitfields(s, sep):
	res = []
	ns = len(s)
	nsep = len(sep)
	i = j = 0
	while j+nsep <= ns:
		if s[j:j+nsep] = sep:
			res.append(s[i:j])
			i = j = j + nsep
		else:
			j = j + 1
	res.append(s[i:])
	return res

# Cherche une sous-chaîne
index_error = 'string.index n\'a pas pu trouver une sous-chaîne'
def index(s, sub):
	n = len(sub)
	for i in range(len(s) - n):
		if sub = s[i:i+n]: return i
	raise index_error, (s, sub)

# Convertit une chaîne en un entier
atoi_error = 'string.atoi s\'est vu passée un argument non-numérique'
def atoi(str):
	s = str
	if s[:1] in '+-': s = s[1:]
	if not s: raise atoi_error, str
	for c in s:
		if c not in digits: raise atoi_error, str
	return eval(str)

# Justifie à gauche une chaîne
def ljust(s, width):
	n = len(s)
	if n >= width: return s
	return s + ' '*(width-n)

# Justifie à droite une chaîne
def rjust(s, width):
	n = len(s)
	if n >= width: return s
	return ' '*(width-n) + s

# Centre une chaîne
def center(s, width):
	n = len(s)
	if n >= width: return s
	return ' '*((width-n)/2) +  s + ' '*(width -(width-n)/2)

# Ajoute des zéros à un nombre; par exemple, (12, 3) --> '012' et
# (-3, 3) --> '-03'.
# Fonctionnalité décadente : l'argument peut être une chaîne ou un nombre
# (Cet usage est obsolète; il est recommandé de passer une chaîne à cette
# fonction, comme pour ljust)
def zfill(x, width):
	if type(x) = type(''): s = x
	else: s = `x`
	n = len(s)
	if n >= width: return s
	sign = ''
	if s[0] = '-':
		sign, s = '-', s[1:]
	return sign + '0'*(width-n) + s
